package be.donovan.gui.helper.components;

import java.awt.BorderLayout;
import java.awt.Component;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.JFormattedTextField;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.text.NumberFormatter;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.ReflectionUtils;

import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.FormLayout;

public abstract class MVCPanel extends JPanel implements ViewI {
	protected Log logger = LogFactory.getLog(this.getClass());
	@SuppressWarnings("unchecked")
	protected AbstractController controller;

	@SuppressWarnings("unchecked")
	public void setController(AbstractController controller) {
		this.controller = controller;
		controller.setView(this);
		controller.cleanup();
	}

	/**
	 * Create a afterPropertiesSet() method for Spring. Implement it as
	 * getController().initData(). Adapt the MVC framework module as such
	 */
	public void afterPropertiesSet() throws Exception {
		try {
			if (controller == null) {
				logger.warn("No controller set");
			} else {
				controller.initListeners();
				controller.initData();
			}
		} catch (RuntimeException e) {
			JErrorDialog.showError("Error invoking afterPropertiesSet", e);
			throw e;
		}
	}

	@SuppressWarnings("unchecked")
	public AbstractController getController() {
		if(controller==null){
			return new AbstractController() {
			
				@Override
				public void initListeners() {
					// TODO Auto-generated method stub
			
				}
			
				@Override
				public void initData() {
					// TODO Auto-generated method stub
			
				}
			
			};
		}
		return controller;
	}

	@SuppressWarnings("unchecked")
	public Map<Field, JTextField> addGenericInputPanel(JPanel panel,Class clazz,
			String... ignoreFields) {
		Map<Field, JTextField> mappings = new HashMap<Field, JTextField>();
		DefaultFormBuilder builder = new DefaultFormBuilder(new FormLayout(""));
		builder.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		builder.appendColumn("right:pref");
		builder.appendColumn("3dlu");
		builder.appendColumn("fill:max(pref; 100px)");
		builder.appendColumn("5dlu");
		builder.appendColumn("right:pref");
		builder.appendColumn("3dlu");
		builder.appendColumn("fill:max(pref; 100px)");
		Field[] fields = clazz.getDeclaredFields();

		for (Field field : fields) {
			String fieldName = field.getName();
			if (!Arrays.asList(ignoreFields).contains(fieldName)) {
				JTextField textField = new JTextField();
				if (Integer.class.isAssignableFrom(field.getType())) {
					NumberFormatter numberFormatter = new NumberFormatter();
					numberFormatter.setValueClass(Integer.class);
					textField = new JFormattedTextField(numberFormatter);
				}
				if (Double.class.equals(field.getType())) {
					textField = new CurrencyTextField(0.5);
					
				}
				mappings.put(field, textField);
				
				builder
						.append(getMessage(fieldName),
								textField);
				builder.nextLine();
			}
		}
		panel.add(builder.getPanel(), BorderLayout.CENTER);
		return mappings;
	}


	private String getMessage(String fieldName) {
		if(controller==null){
			return fieldName;
		}
		return controller.getMessage(fieldName);
	}

	public void mapToObject(Object object, Map<Field, JTextField> mappings) {
		for (Map.Entry<Field, JTextField> entry : mappings.entrySet()) {
			ReflectionUtils.makeAccessible(entry.getKey());
			ReflectionUtils.setField(entry.getKey(), object, entry.getValue() instanceof JFormattedTextField ? ((JFormattedTextField)entry.getValue()).getValue():entry.getValue()
					.getText());
			
		}
	}

}
